package com.imut.lagain.interceptor;

import com.imut.lagain.service.IDataOperationLogService;
import com.imut.lagain.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;

import java.util.Map;

/**
 * 数据操作日志拦截器
 * 用于记录数据变更操作日志
 */
@Component
public class DataOperationLogInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(DataOperationLogInterceptor.class);
    private final IDataOperationLogService dataOperationLogService;
    private final JwtUtil jwtUtil;
    
    @Autowired
    public DataOperationLogInterceptor(IDataOperationLogService dataOperationLogService, JwtUtil jwtUtil) {
        this.dataOperationLogService = dataOperationLogService;
        this.jwtUtil = jwtUtil;
    }
    
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "Bearer ";
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                              Object handler, Exception ex) {
        try {
        log.info("只记录数据变更操作");
            if (shouldLogDataOperation(request, response)) {
                logDataOperation(request, response);
            }
        } catch (Exception e) {
            log.error("Failed to log data operation: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 记录数据操作日志
     */
    private void logDataOperation(HttpServletRequest request, HttpServletResponse response) {
        log.info("获取用户ID");
        Long userId = getUserIdFromRequest(request);
        if (userId == null) {
            return; // 未认证用户不记录数据操作日志
        }
        
        log.info("获取操作信息");
        String method = request.getMethod();
        String path = request.getRequestURI();
        String operationType = determineOperationType(method, path);
        String tableName = extractTableName(path);
        String recordIdStr = extractRecordId(request, path);
        Long recordId = null;
        if (recordIdStr != null && !recordIdStr.isEmpty()) {
            try {
                recordId = Long.parseLong(recordIdStr);
            } catch (NumberFormatException e) {
                log.warn("Invalid record ID format: {}", recordIdStr);
            }
        }
        
        log.info("获取IP地址");
        String ipAddress = getClientIpAddress(request);
        
        log.info("异步记录数据操作日志");
        try {
            dataOperationLogService.logOperation(
                userId,
                operationType,
                tableName,
                recordId,
                ipAddress,
                null, // oldData - 需要在具体业务中设置
                null  // newData - 需要在具体业务中设置
            );
        } catch (Exception e) {
            log.error("Failed to save data operation log: {}", e.getMessage());
        }
    }
    
    /**
     * 判断是否需要记录数据操作日志
     */
    private boolean shouldLogDataOperation(HttpServletRequest request, HttpServletResponse response) {
        String method = request.getMethod();
        String path = request.getRequestURI();
        int statusCode = response.getStatus();
        
        log.info("只记录成功的数据变更操作");
        if (statusCode < 200 || statusCode >= 300) {
            return false;
        }
        
        log.info("只记录POST、PUT、DELETE操作");
        if (!"POST".equals(method) && !"PUT".equals(method) && !"DELETE".equals(method)) {
            return false;
        }
        
        log.info("跳过认证相关接口");
        if (path.startsWith("/api/auth/")) {
            return false;
        }
        
        log.info("跳过日志查询接口");
        if (path.contains("/logs/") && "GET".equals(method)) {
            return false;
        }
        
        log.info("跳过健康检查和静态资源");
        if (path.startsWith("/actuator/") || 
            path.startsWith("/static/") ||
            path.startsWith("/css/") ||
            path.startsWith("/js/") ||
            path.startsWith("/images/")) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 确定操作类型
     */
    private String determineOperationType(String method, String path) {
        switch (method) {
            case "POST":
                return "CREATE";
            case "PUT":
                if (path.contains("/seal") || path.contains("/activate") || 
                    path.contains("/deactivate") || path.contains("/restore")) {
                    return "UPDATE";
                }
                return "UPDATE";
            case "DELETE":
                return "DELETE";
            default:
                return "UNKNOWN";
        }
    }
    
    /**
     * 从路径中提取表名
     */
    private String extractTableName(String path) {
        log.info("移除API前缀");
        if (path.startsWith("/api/")) {
            path = path.substring(5);
        }
        
        log.info("提取第一个路径段作为表名");
        String[] segments = path.split("/");
        if (segments.length > 0) {
            String tableName = segments[0];
            
        log.info("映射到实际表名");
            switch (tableName) {
                case "capsules":
                    return "memory_capsule";
                case "entries":
                    return "memory_entry";
                case "users":
                    return "user";
                case "passwords":
                    return "final_password";
                case "answers":
                    return "final_answer";
                default:
                    return tableName;
            }
        }
        
        return "unknown";
    }
    
    /**
     * 从请求中提取记录ID
     */
    private String extractRecordId(HttpServletRequest request, String path) {
        try {
        log.info("尝试从路径参数中获取ID");
            @SuppressWarnings("unchecked")
            Map<String, String> pathVariables = (Map<String, String>) request.getAttribute(
                HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            
            if (pathVariables != null) {
        log.info("常见的ID参数名");
                String[] idParams = {"id", "capsuleId", "entryId", "userId", "passwordId"};
                for (String param : idParams) {
                    String value = pathVariables.get(param);
                    if (StringUtils.hasText(value)) {
                        return value;
                    }
                }
            }
            
        log.info("尝试从查询参数中获取ID");
            String id = request.getParameter("id");
            if (StringUtils.hasText(id)) {
                return id;
            }
            
        log.info("尝试从路径中解析数字ID");
            String[] segments = path.split("/");
            for (String segment : segments) {
                if (segment.matches("\\d+")) {
                    return segment;
                }
            }
        } catch (Exception e) {
            log.debug("Failed to extract record ID: {}", e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 从请求中获取用户ID
     */
    private Long getUserIdFromRequest(HttpServletRequest request) {
        try {
        log.info("首先尝试从请求属性中获取（由JWT过滤器设置）");
            Object userIdAttr = request.getAttribute("userId");
            if (userIdAttr instanceof Long) {
                return (Long) userIdAttr;
            }
            
        log.info("如果请求属性中没有，尝试从JWT令牌中解析");
            String token = extractTokenFromRequest(request);
            if (StringUtils.hasText(token) && jwtUtil.validateToken(token)) {
                return jwtUtil.getUserIdFromToken(token);
            }
        } catch (Exception e) {
            log.debug("Failed to get user ID from request: {}", e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 从请求中提取JWT令牌
     */
    private String extractTokenFromRequest(HttpServletRequest request) {
        String authHeader = request.getHeader(AUTHORIZATION_HEADER);
        
        if (StringUtils.hasText(authHeader) && authHeader.startsWith(BEARER_PREFIX)) {
            return authHeader.substring(BEARER_PREFIX.length());
        }
        
        return null;
    }
    
    /**
     * 获取客户端真实IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String[] headerNames = {
            "X-Forwarded-For",
            "X-Real-IP",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_CLIENT_IP",
            "HTTP_X_FORWARDED_FOR"
        };
        
        for (String headerName : headerNames) {
            String ip = request.getHeader(headerName);
            if (StringUtils.hasText(ip) && !"unknown".equalsIgnoreCase(ip)) {
        log.info("多级代理的情况，取第一个IP");
                if (ip.contains(",")) {
                    ip = ip.split(",")[0].trim();
                }
                return ip;
            }
        }
        
        log.info("如果所有代理头都没有，则使用远程地址");
        String remoteAddr = request.getRemoteAddr();
        
        log.info("处理IPv6本地地址");
        if ("0:0:0:0:0:0:0:1".equals(remoteAddr)) {
            return "127.0.0.1";
        }
        
        return remoteAddr;
    }
}
